Skip to content

如何在 Docker 使用 GitLab CI

TLDR

  • GitLab 安裝建議:務必設定 external_url 以確保 SSH 與 HTTP 連結正確,若使用非標準 Port,需同時設定 nginx['listen_port']
  • Volume 掛載:GitLab 的 /var/opt/gitlab 建議使用 Docker Volume 而非 Bind Mount,以避免 artifacts 功能因權限不足而失效。
  • Runner 註冊:若 GitLab 網址為 127.0.0.1localhost,註冊時需手動指定 clone_url,否則 Runner 無法連線。
  • Docker Executor 權限:若需在 CI 中執行 Docker 指令,需將 /var/run/docker.sock 掛載至 Runner,並在 config.toml 中將 privileged 設為 true
  • 網路模式:Runner 的 network_mode 不可設為 host,建議使用 gitlab_default 以確保 Runner 能與 GitLab 容器正常通訊。
  • CI 變數限制:Docker Image 名稱僅支援小寫,若專案名稱含大寫,請使用 $CI_PROJECT_PATH_SLUG 變數。

在 Docker 上安裝 GitLab

在 Docker 環境中部署 GitLab 時,設定檔的正確性至關重要。

關鍵設定與注意事項

  • 什麼情況下會遇到問題:若未正確設定 external_url,GitLab 產生的 SSH 與 HTTP 儲存庫連結將會失效或顯示為亂碼。
  • 解決方案
    • docker-compose.ymlGITLAB_OMNIBUS_CONFIG 中明確指定 external_url
    • 若使用非 80 Port,必須同步設定 nginx['listen_port']
    • 避免使用 Bind Mount 掛載 /var/opt/gitlab,改用 Docker Volume 以解決 artifacts 功能的權限問題。
    • 若出現「invalid port specification」錯誤,請將 Port 對應(如 5022:22)加上引號。
yaml
# docker-compose.yml 範例片段
environment:
  GITLAB_OMNIBUS_CONFIG: |
    external_url 'http://127.0.0.1:5080/'
    nginx['listen_port'] = 80
    gitlab_rails['gitlab_shell_ssh_port'] = 5022
ports:
  - "5080:80"
  - "5022:22"

在 Docker 上安裝與註冊 GitLab Runner

Runner 的設定決定了 CI/CD 任務能否順利執行。

註冊與配置重點

  • 什麼情況下會遇到問題:當 GitLab 容器使用 127.0.0.1localhost 作為網址時,Runner 註冊後會因為無法解析位址而無法拉取程式碼。
  • 解決方案
    • 註冊後編輯 config.toml,手動加入 clone_url 指向 GitLab 容器的正確 IP。
    • 若要執行 Docker 指令(如 docker build),必須掛載 docker.sock
toml
# config.toml 設定範例
[[runners]]
  url = "http://172.20.0.2"
  clone_url = "http://172.20.0.2"
  executor = "docker"
  [runners.docker]
    privileged = true
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
    network_mode = "gitlab_default"

WARNING

network_mode 切勿設定為 host,否則可能導致 GitLab 服務回應異常。


GitLab CI 實例:.NET 6 專案

透過 .gitlab-ci.yml 定義 Build、List、Deploy 三個階段,實現自動化流程。

核心實作細節

  • 什麼情況下會遇到問題:在 list-job 中輸出檔案路徑時,若檔案名稱包含中文,會因編碼問題被轉譯。
  • 解決方案:使用 git config --global core.quotepath false 關閉特殊字元轉譯。
  • 部署注意事項:由於 Docker Image 名稱僅支援小寫,請使用 $CI_PROJECT_PATH_SLUG 變數來動態產生 Image 名稱。
yaml
# .gitlab-ci.yml 範例片段
deploy-job:
  stage: deploy
  script:
    - cd build
    - docker build --tag $CI_PROJECT_PATH_SLUG:latest .
    - docker stop $CI_PROJECT_NAME || true && docker rm $CI_PROJECT_NAME || true
    - docker run -d -p 9080:80 --name $CI_PROJECT_NAME $CI_PROJECT_PATH_SLUG:latest

總結

透過將 Runner 的 privileged 權限開啟並掛載 docker.sock,可以讓 Runner 直接呼叫宿主機的 Docker Engine 進行容器化部署,這是最適合在單機 Docker 環境下進行 CI/CD 的做法。


異動歷程

    • 初版文件建立。